//
//  LYSystemPermission.m
//  LYAppMoudle
//
//  Created by 林域 on 2018/12/18.
//  Copyright © 2018 林域. All rights reserved.
//

#import "LYSystemPermission.h"
@import EventKit;
@import CoreTelephony;
@import CoreLocation;
@import UIKit;
@import Photos;
@import AssetsLibrary;
@import Contacts;
@import CoreBluetooth;
@import AddressBook;
@import MediaPlayer;
@import UserNotifications;

@interface LYSystemPermission ()<CLLocationManagerDelegate>

@end

@implementation LYSystemPermission

static LYSystemPermission *sharedSingleton = nil;
+ (id)allocWithZone:(struct _NSZone *)zone
{
    if (!sharedSingleton) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedSingleton = [super allocWithZone:zone];
        });
    }
    return sharedSingleton;
}

- (id)init
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedSingleton = [super init];
    });
    return sharedSingleton;
}

+ (instancetype)sharedInstance

{
    return [[self alloc] init];
}


- (void)LYPermission_RequestAuthorizationWithType:(LYPermissionType)type
                                 PermissionHandle:(handlePermission)handle
                                         unHandle:(unhandlePermission)unHandle{
    switch (type) {
        case LYPermissionType_Photo:
            [self ly_requestPhotoLibraryPermission:handle unhandle:unHandle];
            break;
        case LYPermissionType_Contact:
            [self ly_requestContactPermission:handle unhandle:unHandle];
            break;
        case LYPermissionType_NetWork:
            [self ly_requestNetworkPermission:handle unhandle:unHandle];
            break;
        case LYPermissionType_Calendar:
            [self ly_requestCalendarPermission:handle unhandle:unHandle];
            break;
        case LYPermissionType_MicroPhone:
            [self ly_requestAudioPermission:handle unhandle:unHandle];
            break;
        case LYPermissionType_Location:
            
            break;
        case LYPermissionType_LocationAlways:
            
            break;
        case LYPermissionType_LocationWhenInUse:
            
            break;
        case LYPermissionType_Notification:
            [self ly_requestNotificationPermission:handle unhandle:unHandle];
            break;
        case LYPermissionType_BlueTooth:
            [self ly_requestBlueToothPermission:handle unhandle:unHandle];
            break;
        case LYPermissionType_Camera:
            [self ly_requestCameraPermission:handle unhandle:unHandle];
            break;
    }
}

#pragma mark - photo -
-(void)ly_requestPhotoLibraryPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle{
    PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
    if (authStatus == PHAuthorizationStatusNotDetermined) { //未询问过用户
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    handle ? handle(): nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    unhandle ? unhandle(): nil;
                });
            }
        }];
    }else if (authStatus == PHAuthorizationStatusAuthorized){
        handle ? handle(): nil;
    }else{
        unhandle ? unhandle(): nil;
    }
}

#pragma mark - network -
-(void)ly_requestNetworkPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle{
    CTCellularData *cellularData = [[CTCellularData alloc] init];
    CTCellularDataRestrictedState authState = cellularData.restrictedState;
    if (authState == kCTCellularDataRestrictedStateUnknown) {
        cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){
            if (state == kCTCellularDataNotRestricted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    handle ? handle() : nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    unhandle ? unhandle() : nil;
                });
            }
        };
    }else if (authState == kCTCellularDataNotRestricted){
        handle ? handle() : nil;
    }else{
        unhandle ? unhandle() : nil;
    }
}

#pragma mark - contact -
//beyond ios9
-(void)ly_requestContactPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle{
    CNAuthorizationStatus authStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    if (authStatus == CNAuthorizationStatusNotDetermined) {
        CNContactStore *contactStore = [[CNContactStore alloc] init];
        [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    handle ? handle() : nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    unhandle ? unhandle() : nil;
                });
            }
        }];
    }else if (authStatus == CNAuthorizationStatusAuthorized){
        handle ? handle() : nil;
    }else{
        unhandle ? unhandle() : nil;
    }
}

#pragma mark - Calendar -
- (void)ly_requestCalendarPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle{
    
    EKAuthorizationStatus authStatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
    if (authStatus == EKAuthorizationStatusNotDetermined) {
        EKEventStore *eventStore = [[EKEventStore alloc] init];
        [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    handle ? handle() : nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    unhandle ? unhandle() : nil;
                });
            }
        }];
    }else if (authStatus == EKAuthorizationStatusAuthorized){
        handle ? handle() : nil;
    }else{
        unhandle ? unhandle() : nil;
    }
}

#pragma mark - Camera -
- (void)ly_requestCameraPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle{
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (authStatus == AVAuthorizationStatusNotDetermined) {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    handle ? handle() : nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    unhandle ? unhandle() : nil;
                });
            }
        }];
        
    }else if(authStatus == AVAuthorizationStatusAuthorized){
        handle ? handle() : nil;
    }else{
        unhandle ? unhandle() : nil;
    }
}

#pragma mark - audio -
- (void)ly_requestAudioPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle{
    
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    if (authStatus == AVAuthorizationStatusNotDetermined) {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    handle ? handle() : nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    unhandle ? unhandle() : nil;
                });
            }
        }];
        
    }else if(authStatus == AVAuthorizationStatusAuthorized){
        handle ? handle() : nil;
    }else{
        unhandle ? unhandle() : nil;
    }
}

#pragma mark - Notification -
- (void)ly_requestNotificationPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle
{
    if (@available(iOS 10, *))
    {
        UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter];
        [center requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    handle ? handle() : nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    unhandle ? unhandle() : nil;
                });
            }            
        }];
    }
    else if(@available(iOS 8 , *))
    {
        UIApplication * application = [UIApplication sharedApplication];
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]];
        [application registerForRemoteNotifications];
    }
    else
    {
        UIApplication * application = [UIApplication sharedApplication];
        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
        [application registerForRemoteNotifications];
    }
}

#pragma mark - Bluetooth
- (void)ly_requestBlueToothPermission:(handlePermission)handle unhandle:(unhandlePermission)unhandle
{
    CBPeripheralManagerAuthorizationStatus authStatus = [CBPeripheralManager authorizationStatus];
    if (authStatus == CBPeripheralManagerAuthorizationStatusNotDetermined) {
        CBCentralManager *cbManager = [[CBCentralManager alloc] init];
        [cbManager scanForPeripheralsWithServices:nil
                                          options:nil];
    }else if (authStatus == CBPeripheralManagerAuthorizationStatusAuthorized) {
        handle ? handle() : nil;
    }else{
        unhandle ? unhandle() : nil;
    }
}


@end
